﻿using System.Web;
using NHibernate;
using NHibernate.Cfg;
using Mayfair.Core.Common.Util;
using Common.Logging;

namespace Mayfair.Core.Common.Service
{
    public sealed class SessionBuilder:ISessionBuilder
    {
        private static readonly ILog log = LogManager.GetLogger(typeof(SessionBuilder));
        private static ISession currentSession;
        private static ISessionFactory sessionFactory;
       
        /// <summary>
        /// 
        /// </summary>
        /// <returns></returns>
        public ISession getSession()
        {
            ISessionFactory factory = getSessinFactory();
            ISession session = getExistingOrNewSession(factory);
            Logger.Debug(this, "Using ISession " + session.GetHashCode());
            return session;
        }

        /// <summary>
        /// 
        /// </summary>
        /// <returns></returns>
        public Configuration getConfiguretion()
        {
            var configration = new Configuration();
            configration.Configure();
            return configration;
        }

        /// <summary>
        /// 
        /// </summary>
        /// <returns></returns>
        private ISessionFactory getSessinFactory()
        {
            lock (this) 
            {
                if (sessionFactory == null)
                {
                    Configuration configration = getConfiguretion();
                    sessionFactory = configration.BuildSessionFactory();
                }
                return sessionFactory;
            }            
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="factory"></param>
        /// <returns></returns>
        private ISession getExistingOrNewSession(ISessionFactory factory)
        { 
        
            if (HttpContext.Current != null)
            {
                ISession session = getExistingWebSession();
                if (session == null)
                {
                    session = openSessionAndAddToContext(factory);
                }
                else if (!session.IsOpen)
                {
                    session = openSessionAndAddToContext(factory);
                }
                return session;
            }
            if (currentSession == null)
            {
                currentSession = factory.OpenSession();
            }
            else if (!currentSession.IsOpen)
            {
                currentSession = factory.OpenSession();
            }
            return currentSession;
        }

        /// <summary>
        /// 
        /// </summary>
        /// <returns></returns>
        private ISession getExistingWebSession()
        {
            return HttpContext.Current.Items[GetType().FullName] as ISession;
        }

        private ISession openSessionAndAddToContext(ISessionFactory factory)
        {
            ISession session = factory.OpenSession();
            HttpContext.Current.Items.Remove(GetType().FullName);
            HttpContext.Current.Items.Add(GetType().FullName, session);
            return session;
        }

        /// <summary>
        /// 
        /// </summary>
        public static void resetSession()
        {
            var builder = new SessionBuilder();
            builder.getSession().Dispose();
        }
    }
}
